import os
import json
import requests
import time
import schedule
from time import sleep
from tb_device_mqtt import TBDeviceMqttClient

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
from iotdb.Session import Session

from system.process_phm_csv import process_data
from system.predict_csv import start_application

# ThingsBoard服务器URL
THINGSBOARD_URL = 'http://127.0.0.1:8080/api/v1/'
ACCESS_TOKEN_RUL = 't13vxnxfrbpe3n2q5yqn'

ACCESS_TOKEN_BEARING1_3 = 'HftfNklEgEvNJxMAS4ao'


def import_data(start_time, end_time):
    # creating session connection.
    ip = "127.0.0.1"
    port_ = "6667"
    username_ = "root"
    password_ = "root"
    session = Session(ip, port_, username_, password_, fetch_size=1024, zone_id="UTC+8", enable_redirection=True)

    session.open(False)

    # start_time = datetime(2024, 1, 1, 16, 33, 1)
    # end_time = datetime(2024, 1, 1, 16, 33, 2)
    start_time = start_time
    end_time = end_time

    start_timestamp = int(start_time.timestamp() * 1000)
    end_timestamp = int(end_time.timestamp() * 1000)

    result = session.execute_query_statement(
        "select * from root.phm2012.no1.Bearing1_3 WHERE time >= " + str(start_timestamp) + " AND time < " + str(
            end_timestamp))
    data = result.todf()

    if len(data) > 2560:
        data_chunks = [data.iloc[i:i + 2560].copy() for i in range(0, len(data), 2560)]
    else:
        data_chunks = [data]
    data_chunks = np.stack([chunk.values for chunk in data_chunks])
    session.close()
    return data_chunks


def send2thingsboard(datas):
    # data = pd.DataFrame(mean_data)
    messages = []
    for index, data in datas.iterrows():
        message = {
            'ts': data[0],
            "values": {
                "horizontal": data[1],
                "vertical": data[2]
            }
        }
        # message = {
        #     "horizontal": data[1],
        #     "vertical": data[2]
        # }
        messages.append(message)
    url = f"{THINGSBOARD_URL}{ACCESS_TOKEN_BEARING1_3}/telemetry"
    response = requests.post(url, data=json.dumps(messages), headers={'Content-Type': 'application/json'})
    if response.status_code == 200:
        print(f"Data sent successfully")
    else:
        print(f"Failed to send data for index {index}: {response.status_code} - {response.text}")


def send2thingsboard_rul(datas):
    messages = []
    for data in datas:
        message = {
            'ts': data[0],
            "values": {
                "rul": data[1]
            }
        }
        messages.append(message)
    url = f"{THINGSBOARD_URL}{ACCESS_TOKEN_RUL}/telemetry"
    response = requests.post(url, data=json.dumps(messages), headers={'Content-Type': 'application/json'})
    if response.status_code == 200:
        print(f"Data sent successfully")
    else:
        print(f"Failed to send data: {response.status_code} - {response.text}")

def send_data(start_time, end_time, time_since_start):
    print(f"Importing data, current counter time: {start_time} seconds")
    raw_datas = import_data(start_time, end_time)

    y_pred_list = []
    for raw_data in raw_datas:
        raw_data = pd.DataFrame(raw_data, columns=['Time', 'horizontal', 'vertical'])
        # 修改之前传递与原始数据
        send2thingsboard(raw_data)
        time = raw_data['Time'][0]
        raw_data = raw_data.iloc[:, 1:]

        # print(f"Importing data length {len(raw_data)}")
        remaining_life = predict(raw_data, time_since_start, model_name)
        # print(f"predict value are  {remaining_life}")
        y_pred_list.append([time, remaining_life])
    print(y_pred_list)
    send2thingsboard_rul(y_pred_list)




def predict(raw_data, time_since_start, model="crate"):
    global model_name, model_path, data_path, save_path
    model_name = model
    model_path_new = os.path.join(model_path, model_name)
    data = process_data(raw_data, time_since_start)
    y_pred = start_application(model_name, model_path_new, data_path, save_path, data)
    return y_pred


def job():
    global counter_time
    counter_time += 10  # 每次增加 10 秒
    # 将计时器的秒数加到起始时间
    end_time = bearing_start_time + timedelta(seconds=counter_time)
    start_time = end_time - timedelta(seconds=10)
    send_data(start_time, end_time, counter_time // 10)


# dependently of request method we send different data back
def on_server_side_rpc_request(request_id, request_body):
    print(request_id, request_body)
    if request_body["method"] == "getCPULoad":
        client.send_rpc_reply(request_id, {"CPU percent"})
    elif request_body["method"] == "getMemoryUsage":
        client.send_rpc_reply(request_id, {"Memory"})
    else:
        client.send_rpc_reply(request_id, {"error": "unknown method"})


token1 = "yygk42lgziaz74uobzlk"
token2 = "49pazwksi1xb1tdeg8ao"
# global client
client = TBDeviceMqttClient("127.0.0.1", 1883, username=token2)
client.set_server_side_rpc_request_handler(on_server_side_rpc_request)
client.connect()

# 设置开始时间为 2024年1月1日 00:00:00
bearing_start_time = datetime(2024, 1, 1, 16, 33, 1)
counter_time = 0  # 计时器的秒数
model_name = "crate"
model_path = "./system/model"
data_path = "./system/data/system_csv/"
save_path = "./system/predict_result"

if __name__ == '__main__':
    schedule.every(10).seconds.do(job)
    while True:
        schedule.run_pending()
        time.sleep(1)  # 等待 1 秒，避免占用过多 CPU 资源
